package cn.iocoder.yudao.module.security.service.device;

import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.util.*;

import cn.iocoder.yudao.module.security.controller.admin.device.vo.*;
import cn.iocoder.yudao.module.security.dal.dataobject.device.SecurityDeviceDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.security.dal.mysql.device.SecurityDeviceMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.security.enums.ErrorCodeConstants.*;

/**
 * 设备接入 Service 实现类
 *
 * @author cai
 */
@Slf4j
@Service
@Validated
public class SecurityDeviceServiceImpl implements SecurityDeviceService {

    @Resource
    private SecurityDeviceMapper deviceMapper;

    @Override
    public Long createDevice(SecurityDeviceSaveReqVO createReqVO) {
        // 插入
        SecurityDeviceDO device = BeanUtils.toBean(createReqVO, SecurityDeviceDO.class);
        deviceMapper.insert(device);
        // 返回
        return device.getId();
    }

    @Override
    public void updateDevice(SecurityDeviceSaveReqVO updateReqVO) {
        // 校验存在
        validateDeviceExists(updateReqVO.getId());
        // 更新
        SecurityDeviceDO updateObj = BeanUtils.toBean(updateReqVO, SecurityDeviceDO.class);
        deviceMapper.updateById(updateObj);
    }

    @Override
    public void deleteDevice(Long id) {
        // 校验存在
        validateDeviceExists(id);
        // 删除
        deviceMapper.deleteById(id);
    }

    private void validateDeviceExists(Long id) {
        if (deviceMapper.selectById(id) == null) {
            throw exception(DEVICE_NOT_EXISTS);
        }
    }

    @Override
    public SecurityDeviceDO getDevice(Long id) {
        return deviceMapper.selectById(id);
    }

    @Override
    public PageResult<SecurityDeviceDO> getDevicePage(SecurityDevicePageReqVO pageReqVO) {
        return deviceMapper.selectPage(pageReqVO);
    }

    @Override
    public int syncStatus() {
        List<SecurityDeviceDO> securityDeviceDOS = deviceMapper.selectList();
        // curl -X 'GET' \
        //  'http://192.168.254.100/api/v2/status/system' \
        //  -H 'accept: application/json' \
        //  -H 'Authorization: Basic YWRtaW46MTIzNDU2' \
        //  -H 'x-api-key: 11ccb5c9393e18fec385a5ff2df9932d'


        int res = 0;
        for (SecurityDeviceDO securityDeviceDO : securityDeviceDOS) {
            if (StringUtils.isNotBlank(securityDeviceDO.getIpAddress()) && StringUtils.isNotBlank(securityDeviceDO.getDeviceUsername()) && StringUtils.isNotBlank(securityDeviceDO.getDevicePassword())) {
                try {
                    String basicAuth = HttpUtil.buildBasicAuth(securityDeviceDO.getDeviceUsername(), securityDeviceDO.getDevicePassword(), Charset.forName("UTF-8"));
                    String url = "http://" + securityDeviceDO.getIpAddress() + "/api/v2/status/system";
                    HttpRequest req = HttpUtil.createGet(url);
                    req.header("Authorization", basicAuth);
                    req.header("accept", "application/json");
                    req.timeout(6000);
                    HttpResponse response = req.execute();
                    if (response.isOk()) {
                        /*
                        {
                          "code": 200,
                          "status": "ok",
                          "response_id": "SUCCESS",
                          "message": "",
                          "data": {
                            "platform": "VMware Virtual Machine",
                            "serial": "",
                            "netgate_id": "7862a2b8152a92e392e4",
                            "uptime": "00 Hour 24 Minutes 28 Seconds",
                            "bios_vendor": "Phoenix Technologies LTD",
                            "bios_version": "6.00",
                            "bios_date": "07/29/2019",
                            "kernel_pti": true,
                            "mds_mitigation": "inactive",
                            "temp_c": null,
                            "temp_f": null,
                            "cpu_model": "Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz",
                            "cpu_load_avg": [
                              0.56,
                              0.45,
                              0.32
                            ],
                            "cpu_count": 2,
                            "cpu_usage": 28,
                            "mbuf_usage": 0,
                            "mem_usage": 12,
                            "swap_usage": 0,
                            "disk_usage": 6
                          }
                        }
                         */
                        JSONObject object = JSON.parseObject(response.body());
                        JSONObject data = object.getJSONObject("data");
                        if (data != null) {
                            Integer cpuUsage = data.getInteger("cpu_usage");
                            Integer memUsage = data.getInteger("mem_usage");
                            Integer diskUsage = data.getInteger("disk_usage");
                            if (Objects.nonNull(cpuUsage)) {
                                securityDeviceDO.setDeviceCpu(new BigDecimal(cpuUsage).divide(new BigDecimal(10), 2, BigDecimal.ROUND_HALF_UP));
                            }
                            if (Objects.nonNull(memUsage)) {
                                securityDeviceDO.setDeviceMemory(new BigDecimal(memUsage));
                            }
                            if (Objects.nonNull(diskUsage)) {
                                securityDeviceDO.setDeviceDisk(new BigDecimal(diskUsage));
                            }
                            securityDeviceDO.setDeviceStatus("1");
                            securityDeviceDO.setLastOnlineTime(LocalDateTime.now());
                            deviceMapper.updateById(securityDeviceDO);
                            res++;
                            log.info("同步设备状态成功，url: {}, status: {}, response: {}", url, response.getStatus(), response.body());
                        } else {
                            log.warn("同步设备状态失败，url: {}, status: {}, response: {}", url, response.getStatus(), response.body());
                            securityDeviceDO.setDeviceStatus("2");
                            deviceMapper.updateById(securityDeviceDO);
                        }
                    } else {
                        securityDeviceDO.setDeviceStatus("2");
                        deviceMapper.updateById(securityDeviceDO);
                        log.warn("同步设备状态失败，url: {}, status: {}, response: {}", url, response.getStatus(), response.body());
                    }
                } catch (Exception e) {
                    log.error("同步设备状态失败", e);
                    securityDeviceDO.setDeviceStatus("2");
                    deviceMapper.updateById(securityDeviceDO);
                }
            } else {
                securityDeviceDO.setDeviceStatus("2");
                deviceMapper.updateById(securityDeviceDO);
            }
        }
        return res;
    }

}